package com.baturu.vin.hyundai.service.impl;

import com.alibaba.fastjson.JSON;
import com.baturu.vin.base.exception.EPCDataNotStandardException;
import com.baturu.vin.dto.CarTypeBuilderDTO;
import com.baturu.vin.hyundai.constant.HyundaiKiaSource;
import com.baturu.vin.hyundai.dal.dao.HyundaiKiaBtrRelationDAO;
import com.baturu.vin.hyundai.dal.dao.HyundaiKiaCommonDAO;
import com.baturu.vin.hyundai.dal.dao.HyundaiKiaNoCarSystemDAO;
import com.baturu.vin.hyundai.dal.entity.HyundaiKiaCombinationEntity;
import com.baturu.vin.hyundai.dto.HyundaiAttributeEntity;
import com.baturu.vin.hyundai.dto.HyundaiKiaBtrRelationEntity;
import com.baturu.vin.hyundai.dto.HyundaiKiaVehicleDTO;
import com.baturu.vin.service.EPCVinCacheService;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class HyundaiKiaCarAnalyser implements InitializingBean {

    @Autowired
    private HyundaiKiaCommonDAO commonDAO;

    @Autowired
    private HyundaiKiaBtrRelationDAO btrRelationDAO;

    @Autowired
    private EPCVinCacheService vinCacheService;
    @Autowired
    private HyundaiKiaNoCarSystemDAO hyundaiKiaLogDAO;

    /**
     * 根据车架解析结果生成btrId
     * @param analyseResult 车架解析结果
     * @return btrId（或集合）
     */
    protected String analysisBtrIdAndBuildCarType (HyundaiKiaVehicleDTO analyseResult) throws EPCDataNotStandardException, InvocationTargetException, IllegalAccessException {
        if(Objects.isNull(analyseResult)){
            log.info("vin信息为空1");
            return null;
        }

        // 获取btrId相关信息
        HyundaiKiaBtrRelationEntity relationEntity = getRelationDTO(analyseResult);
        if (relationEntity == null) {
            log.info("btrId相关信息信息为空1");
            return null;
        }

        // 检查btrId关联是否存在
        synchronized (btrRelationDAO) {
            String btrId = btrRelationDAO.queryBtrIdByRelation(relationEntity);
            if (btrId != null) {
                return btrId;
            }

            // 不存在则根据数据生成btrId、构建CarTypeBuilderDTO
            relationEntity.setBtrId(getBtrId(relationEntity));
            CarTypeBuilderDTO carTypeBuilder = transformCarTypeBuilder(analyseResult, relationEntity);
            if (carTypeBuilder == null) {
                log.info("构建CarTypeBuilderDTO为空1");
                return null;
            }
            try {
                // 这里一旦冲突就不再对qp_cartype表也做插入，但冲突其本身也意味着其他线路已经创建了该数据
                btrRelationDAO.insertNewRelation(Lists.newArrayList(relationEntity));
                vinCacheService.saveNewCarType(Lists.newArrayList(carTypeBuilder));
            } catch (DuplicateKeyException ignore) {}
            return relationEntity.getBtrId();
        }
    }

    /**
     * 根据车架解析结果返回车型构建实体
     * @param analyseResult 车架解析结果
     * @return 车型构建实体
     */
    @SuppressWarnings("ALL")
    protected CarTypeBuilderDTO transformCarTypeBuilder (HyundaiKiaVehicleDTO analyseResult, HyundaiKiaBtrRelationEntity relation) throws InvocationTargetException, IllegalAccessException {
        // 获取EPC定义车型开始构建数据
        String bpno = analyseResult.getBpno();
        Map<String, Object> basicCarType = commonDAO.queryEpcCarTypeByBpno(bpno);
        if (MapUtils.isEmpty(basicCarType)) {
            //这里有时候会查不到基础车型信息（车系），说明这个车系现在可能没有做自解析
            //请定期留意车型数量，考虑是否需要做此车型的自解析
            log.warn("现代起亚有询价到Ignore的车型：{}", bpno);
            hyundaiKiaLogDAO.insertNoAnalyseVin(analyseResult.getVinCode(), bpno);
            return null;
        }

        // 获取车型参数转义数据
        String combination = analyseResult.getCombination();
        List<HyundaiAttributeEntity> majorParameter = analyseResult.getMajorAttributeJson();
        List<HyundaiAttributeEntity> attributeFromDB = commonDAO.queryMajorAttributeByCode(HyundaiKiaSource.VEHICLE_INFO, bpno, majorParameter);

        Map<String, Object> carTypeParameter = attributeFromDB.stream()
                .filter(a -> Objects.nonNull(a.getRemark()))
                .map(ii -> (Map<String, Object>) JSON.parseObject(ii.getRemark(), Map.class)).flatMap(iii ->
                iii.entrySet().stream().map(e -> {
                    Map<String, Object> item = new HashMap<>();
                    String key = e.getKey();
                    item.put("key", key);
                    item.put("value", e.getValue());
                    return item;
                })
        ).collect(Collectors.toMap(
                m -> MapUtils.getString(m, "key"),
                m -> m.get("value"),
                (v1, v2) -> v1));
        Set<String> featureCodes = analyseResult.getFeatureCodesJson().stream().map(f -> f.getCode()).collect(Collectors.toSet());
        String dis = MapUtils.getString(carTypeParameter, "displacement");
        String displacement = StringUtils.isNotBlank(dis)?
                dis + (turboCodes.stream().anyMatch(c -> featureCodes.contains(c)) ? "T" : "L"):"";
        carTypeParameter.put("displacement", displacement);

        // EPC基本车型数据
        String btrId = relation.getBtrId();
        int epcCarTypeId = relation.getVehicleEpcCarTypeId();
        String engineCode = relation.getEngineCode();
        String transmissionCode = relation.getTransmissionCode();

        String btrBrand = MapUtils.getString(basicCarType, "brand");
        String btrSubBrand = MapUtils.getString(basicCarType, "subBrand");
        int carSystemId = MapUtils.getInteger(basicCarType, "carSystemId");
        String carSystemName = MapUtils.getString(basicCarType, "carSystemName");
        String chassis = bpno;
        String productTime = getYearFormBasic(basicCarType, relation.getProductTime()) + "";

        // 具体描述
        String gearsNum = MapUtils.getString(carTypeParameter, "gearsNum");
        String transmissionType = MapUtils.getString(carTypeParameter, "transmissionType");
        String carType = MapUtils.getString(carTypeParameter, "carType");
        String salesName = Stream.of(displacement, gearsNum, transmissionType, carType)
                .filter(StringUtils::isNotBlank)
                .map(String::trim)
                .collect(Collectors.joining(" "));
        salesName = StringUtils.isBlank(salesName) ? carSystemName : salesName;

        CarTypeBuilderDTO carTypeBuilder = new CarTypeBuilderDTO();
        BeanUtils.copyProperties(carTypeBuilder, carTypeParameter);
        carTypeBuilder.setBtrBrand(btrBrand);
        carTypeBuilder.setBtrSubBrand(btrSubBrand);
        carTypeBuilder.setCarSystemId(carSystemId);
        carTypeBuilder.setCarSystem(carSystemName);
        carTypeBuilder.setChassis(chassis);
        carTypeBuilder.setEngineType(engineCode);
        carTypeBuilder.setSalesName(salesName);
        carTypeBuilder.setProductTime(productTime);
        carTypeBuilder.setBtrId(btrId);
        carTypeBuilder.setChassis(bpno);
        return carTypeBuilder;
    }

    /**
     * 获取车型适用年
     * @param basic 车型基本信息
     * @return 适用年范围
     */
    private int getYearFormBasic (Map<String, Object> basic, int makeYear) {
        Integer startYear = MapUtils.getInteger(basic, "startYear");
        Integer endYear = MapUtils.getInteger(basic, "endYear");
        if (startYear != null && startYear > makeYear) {
            return startYear;
        } else if (endYear != null && endYear < makeYear) {
            return endYear;
        } else {
            return makeYear;
        }
    }

    /**
     * 转换btrId
     * @param relation 关联信息
     * @return btrId
     */
    private String getBtrId (HyundaiKiaBtrRelationEntity relation) {
        return Stream.of(
                String.format("HYEPC%07d", relation.getVehicleEpcCarTypeId()),
                relation.getEngineCode(),
                relation.getTransmissionCode(),
                relation.getProductTime() + ""
        ).collect(Collectors.joining("_"));
    }

    /**
     * 查询组合的epcCarTypeId
     * @param analyseResult 车架解析结果
     * @return 组合的epcCarTypeId集合
     */
    private HyundaiKiaBtrRelationEntity getRelationDTO (HyundaiKiaVehicleDTO analyseResult) {
        String bpno = analyseResult.getBpno();
        List<HyundaiAttributeEntity> majorAttributes = analyseResult.getMajorAttributeJson();
        String modelCombination = getModelCombination4Major(bpno, majorAttributes);

        // 转换需要查询的组合
        String vehicleCombination = analyseResult.getCombination();
        Set<String> combinationCodes = Sets.newHashSet(vehicleCombination, modelCombination);

        // 获取epcCarTypeId信息
        int vehicleEpcCarTypeId = 0;
        int modelEpcCarTypeId = 0;
        List<HyundaiKiaCombinationEntity> combinationInfo = commonDAO.queryModelCombination(bpno, combinationCodes);
        for (HyundaiKiaCombinationEntity c : combinationInfo) {
            if (c.getSource() == HyundaiKiaSource.VEHICLE_INFO) {
                vehicleEpcCarTypeId = c.getId();
            } else {
                modelEpcCarTypeId = c.getId();
            }
        }

        // 校验关键数据的vehicle，model不校验
        if (vehicleEpcCarTypeId == 0) {
            String message = String.format("存在无法匹配到Vehicle的组合信息，此信息应该在Vin实时爬取数据时构建，数据存在不一致性风险，请排查：%s", analyseResult.getVinCode());
            log.warn(message);
//            EPCDataNotStandardException epcDataNotStandardException = new EPCDataNotStandardException(message);
//            log.error("获取btrId信息遇到数据缺失问题！", epcDataNotStandardException);
            return null;
        }

        return HyundaiKiaBtrRelationEntity.builder()
                .vehicleEpcCarTypeId(vehicleEpcCarTypeId)
                .modelEpcCarTypeId(modelEpcCarTypeId)
                .engineCode(analyseResult.getEngineCode())
                .transmissionCode(analyseResult.getTransmissionCode())
                .productTime(analyseResult.getMakeYear())
                .build();
    }

    /**
     * 将vin返回的组合信息转化为model对应的组合
     * @param bpno 车型标识
     * @param majorParameter 关键信息参数
     * @return model组合信息
     */
    private String getModelCombination4Major(String bpno, List<HyundaiAttributeEntity> majorParameter) {
        List<HyundaiAttributeEntity> majorAttributesFromDB = commonDAO.queryMajorAttributeByCode(HyundaiKiaSource.MODEL_DETAIL, bpno, majorParameter);
        Set<String> existAttributeCodes = majorAttributesFromDB.stream().map(a -> a.getType() + "|" + a.getCode()).collect(Collectors.toSet());
        return majorParameter.stream().filter(p -> !"WT".equals(p.getType())).map(p -> {
            String type = p.getType();
            String code = p.getCode();
            String key = type + "|" + code;
            if (StringUtils.isBlank(code) || "DT".equals(type) && !existAttributeCodes.contains(key)) {
                return "";
            } else {
                return existAttributeCodes.contains(key) ? code : ".";
            }
        }).collect(Collectors.joining("_"));
    }

    private Set<String> turboCodes = Collections.emptySet();

    @Override
    public void afterPropertiesSet() throws Exception {
        turboCodes = Collections.unmodifiableSet(commonDAO.queryTurboFeatureCodes());
    }
}